/*
 * Javlov - a Java toolkit for reinforcement learning with multi-agent support.
 * 
 * Copyright (c) 2009 Matthijs Snel
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.javlov.world.phys2d;

import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.util.List;

import net.javlov.world.Body;
import net.phys2d.math.Vector2f;

public class ConfigRule {

	public static final int NOTHING = 0,
							STARTVALUE = 1,
							RANDOM = 2;
	
	private Phys2DBody body;
	private Vector2f pos;
	private float rot;
	private int initPosRule, initRotRule, resetPosRule, resetRotRule;
	
	public ConfigRule(Phys2DBody b) {
		body = b;
		pos = (Vector2f)body.getPosition();
		rot = body.getRotation();
	}
	
	public Body getBody() {
		return body;
	}
	
	public void preInit(Phys2DWorld world) {
		if ( ((initPosRule | initRotRule) & RANDOM) != 0 )
			world.disableBody(body);
	}
	
	public void preReset(Phys2DWorld world) {
		if ( ((resetPosRule | resetRotRule) & RANDOM) != 0 )
			world.disableBody(body);
	}

	public void doInit(Phys2DWorld world) {
		setPosition(initPosRule, world);
		setRotation(initRotRule, world);
		if ( ((initPosRule | initRotRule) & RANDOM) != 0 )
			world.enableBody(body);
	}
	
	public void doReset(Phys2DWorld world) {
		setPosition(resetPosRule, world);
		setRotation(resetRotRule, world);
		if ( ((initPosRule | initRotRule) & RANDOM) != 0 )
			world.enableBody(body);
	}
	
	public void setInitConfig(int positionRule, int rotationRule) {
		if ( positionRule + rotationRule < 2 )
			throw new IllegalArgumentException("Doing nothing not allowed for initialisation");
		initPosRule = positionRule;
		initRotRule = rotationRule;
	}
	
	public void setResetConfig(int positionRule, int rotationRule) {
		resetPosRule = positionRule;
		resetRotRule = rotationRule;
	}
	
	protected void setPosition(int rule, Phys2DWorld world) {
		if ( rule == STARTVALUE )
			body.setPosition(pos.x, pos.y);
		else if ( rule == RANDOM ) {
			float width = (float)world.getWidth(),
					height = (float)world.getHeight();
			Rectangle2D.Float bounds = (Rectangle2D.Float) body.getShape().getBounds2D();
			int counter = 0;
			do {
				//System.err.println("Allocating object");
				body.setPosition( 0.5f*bounds.width + (float)Math.random()*(width - bounds.width),
									0.5f*bounds.height + (float)Math.random()*(height - bounds.height));
			} while ( counter++ < 21 && world.intersectsObject( body.getShape().getBounds2D() ) );
			if ( counter > 20 )
				throw new RuntimeException("Could not reposition body after 20 tries.");
		}
	}
	
	protected void setRotation(int rule, Phys2DWorld world) {
		if ( rule == STARTVALUE )
			body.setRotation(rot);
		else if ( rule == RANDOM ){
			int counter = 0;
			//System.out.println("ROTATING" + body.getShape().getBounds2D());
			do {
				body.setRotation((float)(Math.random()*2*Math.PI));
				//System.out.println(body.getShape().getBounds2D());
			} while ( counter++ < 21 && world.intersectsObject( body.getShape().getBounds2D() ) );
			if ( counter > 20 ) {
				System.err.println( world.getIntersectingObjects(body.getShape().getBounds2D()));
				throw new RuntimeException("Could not rerotate body after 20 tries: " + body + ", BOUNDS: " + body.getShape().getBounds2D());
			}
		}	
	}
}
